package com.xiangxiao.rpan.authority.oauth;

import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

/**
 * @Projectname:
 * @Author: xiangxiao
 * @Email: 573768011@qq.com
 * @Data:2023/4/22 23:05
 */
public class RpanAuthenticationProvider implements AuthenticationProvider {
  private final UserDetailsService userDetailsService;

  public RpanAuthenticationProvider(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
  };

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
    String username = token.getName();
    // 从数据库找到的用户
    UserDetails userDetails = null;
    if (username != null) {
      userDetails = userDetailsService.loadUserByUsername(username);
    }

    if (userDetails == null) {

      throw new UsernameNotFoundException("用户名/密码无效");

    } else if (!userDetails.isEnabled()) {

      throw new DisabledException("用户已被禁用");

    } else if (!userDetails.isAccountNonExpired()) {

      throw new AccountExpiredException("账号已过期");

    } else if (!userDetails.isAccountNonLocked()) {

      throw new LockedException("账号已被锁定");

    } else if (!userDetails.isCredentialsNonExpired()) {

      throw new LockedException("凭证已过期");

    }
    // 数据库用户的密码
    String password = userDetails.getPassword();
    // 与authentication里面的credentials相比较
    if (!password.equals(token.getCredentials())) {

      throw new BadCredentialsException("用户名/密码错误");
    }
    // 授权
    return new UsernamePasswordAuthenticationToken(userDetails, password,
      userDetails.getAuthorities());
  }

  @Override
  public boolean supports(Class<?> aClass) {
    // 确保是用户木密码验证模式才走上边的authenticate方法,这步能确保authentication能正确转换类型
    return UsernamePasswordAuthenticationToken.class.equals(aClass);
  }
}
